﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace android_charge.Utils
{
    public class ProcessListener
    {
        private readonly Process process;
        private IntPtr hWinEventHook = IntPtr.Zero;
        private IntPtr mouseHookHandle = IntPtr.Zero;
        private readonly GCHandle callbackHandle;
        private RECT lastRect;

        public Amazon sideTool;

        public string deviceId;
        public ProcessListener(Process process,string deviceId)
        {
            this.process = process;
            this.deviceId = deviceId;
            callbackHandle = GCHandle.Alloc(WinEventCallback);
        }

        // 引入 GetAsyncKeyState API
        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        // 引入 GetForegroundWindow API
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        // 引入 GetWindowThreadProcessId API，用于获取窗口所属的进程ID
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        // 引入 SetWinEventHook API
        [DllImport("user32.dll")]
        private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        // 引入 UnhookWinEvent API
        [DllImport("user32.dll")]
        private static extern bool UnhookWinEvent(IntPtr hWinEventHook);

        // 引入 GetWindowRect API
        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        // 引入 SetWindowPos API
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        // 引入 ShowWindow API
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
        [Serializable]
        [StructLayout(LayoutKind.Sequential)]
        struct WINDOWPLACEMENT
        {
            public int length;
            public int flags;
            public ShowWindowCommands showCmd;
            public POINT ptMinPosition;
            public POINT ptMaxPosition;
            public RECT rcNormalPosition;
        }
        [Serializable]
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public int x;
            public int y;
        }
        private const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
        private const uint WINEVENT_OUTOFCONTEXT = 0;
        private const uint SWP_NOSIZE = 0x0001;
        private const uint SWP_NOMOVE = 0x0002;
        private const uint SWP_NOZORDER = 0x0004;
        private const uint SWP_NOACTIVATE = 0x0010;
        private readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        private readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);

        private delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        private enum ShowWindowCommands : int
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_FORCEMINIMIZE = 11
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        public void Start()
        {
            // 设置窗口位置监听
            WinEventDelegate myDelegate = WinEventCallback;
            hWinEventHook = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, myDelegate, (uint)process.Id, 0, WINEVENT_OUTOFCONTEXT);

            // 启动鼠标钩子
            mouseHookHandle = MouseHook.Start();
            MouseHook.MouseAction += MouseHook_MouseAction;
        }

        public void Stop()
        {
            if (hWinEventHook != IntPtr.Zero)
            {
                UnhookWinEvent(hWinEventHook);
                hWinEventHook = IntPtr.Zero;
            }

            if (mouseHookHandle != IntPtr.Zero)
            {
                MouseHook.Stop(mouseHookHandle);
                mouseHookHandle = IntPtr.Zero;
            }

            if (callbackHandle.IsAllocated)
                callbackHandle.Free();
        }

        private void WinEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            if (eventType == EVENT_OBJECT_LOCATIONCHANGE && hwnd == process.MainWindowHandle)
            {
                UpdateLocation();
                UpdateStatus(); // 新增的状态更新
            }
        }

        private void MouseHook_MouseAction(object sender, EventArgs e)
        {
            IntPtr activeWindowHandle = GetForegroundWindow();
            GetWindowThreadProcessId(activeWindowHandle, out uint processId);

            if (processId == (uint)process.Id)
            {
                if ((GetAsyncKeyState(Keys.ControlKey) & 0x8000) != 0)
                {
                    Console.WriteLine($"在进程 {process.Id} 中按住 Ctrl 键并点击鼠标！");
                }
            }
        }

        public void UpdateLocation()
        {
            IntPtr hwnd = process.MainWindowHandle;
            if (hwnd == IntPtr.Zero)
                return;

            GetWindowRect(hwnd, out RECT rect);
            if (lastRect.Left == rect.Left && lastRect.Top == rect.Top)
                return;

            // 更新sideTool的位置逻辑
            if (rect.Left + rect.Top > 0)
            {
                sideTool.x = rect.Right + sideTool.offsetX;
                sideTool.y = rect.Top + sideTool.offsetY;

                if (sideTool.Handle != IntPtr.Zero)
                {
                    SetWindowPos(sideTool.Handle, IntPtr.Zero, sideTool.x - 57, sideTool.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
                }

                lastRect = rect;
            }
        }
        private static WINDOWPLACEMENT placement = new WINDOWPLACEMENT()
        {
            length = Marshal.SizeOf(placement)
        };
        public void UpdateStatus()
        {
            IntPtr hwnd = process.MainWindowHandle;
            if (sideTool == null || hwnd == IntPtr.Zero || sideTool.Handle == IntPtr.Zero)
                return;

            if (GetWindowPlacement(hwnd, ref placement))
            {
                switch (placement.showCmd)
                {
                    case ShowWindowCommands.SW_HIDE:
                    case ShowWindowCommands.SW_SHOWMINIMIZED:
                    case ShowWindowCommands.SW_SHOWMAXIMIZED:
                    case ShowWindowCommands.SW_SHOWMINNOACTIVE:
                    case ShowWindowCommands.SW_FORCEMINIMIZE:
                        SetWindowPos(sideTool.Handle, Main.isTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
                        ShowWindow(sideTool.Handle, ShowWindowCommands.SW_HIDE);
                        break;
                    case ShowWindowCommands.SW_SHOWNORMAL:
                    case ShowWindowCommands.SW_SHOWNOACTIVATE:
                    case ShowWindowCommands.SW_SHOW:
                        SetWindowPos(sideTool.Handle, Main.isTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
                        ShowWindow(sideTool.Handle, ShowWindowCommands.SW_SHOWNORMAL);
                        break;
                }
            }
        }
    }
}
